﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include "GmStructure.h"
#include "Vector3d.h"
#include "JoinPositions.h"
#include "ElementId.h"

namespace gcmp
{
    class IElementJoin;
    class IInstance;
    class IDocument;
    class ICurve3d;

    class GM_STRUCTURE_EXPORT GbmpJoinConditionUtils
    {
    public:
#pragma region 通用几何连接条件
       // 是否满足几何连接条件
       static bool IsSatisfyGeometryJoin(gcmp::IDocument* pDoc, IElementJoin* pJoin);
#pragma endregion 通用几何连接条件

#pragma region 连接相关几何算法
       //得到与定位线垂直的端线
       static OwnerPtr<ICurve3d> GetPositionEndLine(const IInstance* pInstance, bool isOnStartPoint);
#pragma endregion 连接相关几何算法

       static bool CanInstancesJoinAtEnd(const IInstance* pAttachingInstance, JoinPosition attachingEnd, const IInstance* pAttachedInstance, JoinPosition attachedEnd);
       static bool CanInstancesJoinAtMiddle(const IInstance* pAttachingInstance, JoinPosition attachingEnd, const IInstance* pAttachedInstance);

       static bool AreInstancesHaveVerticalOverlap(const IInstance* pAttachingInstance, const IInstance* pAttachedInstance);
       static bool AreInstancePointAlmostEqual(const IInstance* pAttachingInstance, const Vector3d& attachingEndPt, const IInstance* pAttachedInstance, const Vector3d& attachedEndPt, double tolerance = Constants::DOUBLE_EPS);
       static bool AreInstanceEndPointAndTargetInstanceTouched(const IInstance* pAttachingInstance, JoinPosition attachingEnd, const IInstance* pAttachedInstance);

#pragma region L形连接条件
       // 是否满足L形连接条件
       static bool IsSatisfyLTypeJoin(gcmp::IDocument* pDoc, gcmp::ElementId pAttachingInstanceId, JoinPosition attachingEnd, gcmp::ElementId pAttachedInstanceId, JoinPosition attachedEnd);


       static bool IsSatisfyJoinTypeAndPositionCondition(const IInstance* pAttachingInstance, JoinPosition attachingEnd, const IInstance* pAttachedInstance, JoinPosition attachedEnd, JoinType joinType);
#pragma endregion L形连接条件

       static bool IsParallel(const IInstance* pAttachingInstance, const IInstance* pAttachedInstance);

       static bool AdjustInstancePointForTTypeJoin(IInstance* pAttachingInstance, JoinPosition attachingEnd, const IInstance* pAttachedInstance);

       //A,B构件连接，ptPos为A的连接点，pCurve为B的定位线，ptPos到pCurve的距离小于distEpsilon返回true
       static bool IsSatisfyDistanceCondition(const Vector3d& ptPos, const ICurve3d* pCurve, double distEpsilon);

       static bool HasJoinOnEnd(const IDocument* pDoc, const ElementId& id1, JoinPosition joinPos1, const ElementId& id2, JoinPosition joinPos2);

    private:
       static bool AreInstancesHaveHorizontalOverlap(IInstance* pAttachingInstance, IInstance* pAttachedInstance, JoinPosition attachingEnd, JoinPosition attachedEnd);
       //判断Instance1的定位线是否在Instance2端线内
       static bool IsInstance1PositionCurveInInstance2EndLine(const IInstance* pInstance1, const IInstance* pInstance2, bool isOnInstance2StartPoint);
       static bool HasJoinOnEnd(const IDocument* pDoc, const ElementId& id1, JoinPosition joinPos1, const ElementId& id2);
    };
}

